﻿using Microsoft.Office.Interop.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Excel = Microsoft.Office.Interop.Excel;

namespace SchedulerSupreme
{
    class Parser
    {
        string[] Ugedage = new string[5]{"Mandag","Tirsdag","Onsdag","Torsdag","Fredag"};
        Dictionary<int,string> typer = new Dictionary<int,string>();

        public string parse(string filename)
        {       
            Excel.Application xlApp ;
            Excel.Workbook xlWorkBook ;
            Excel.Worksheet xlWorkSheet ;
            object misValue = System.Reflection.Missing.Value;

            xlApp = new Excel.Application();
            xlWorkBook = xlApp.Workbooks.Open(@filename, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "t", false, false, 0, true, 1, 0);
            xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

            
            for (int i = 1; i <= 3; i++)
                 {
                 Excel.Range range = xlWorkSheet.get_Range("A" + i.ToString(), "AD" + i.ToString());
                 System.Array myvalues = (System.Array)range.Cells.Value;
                 string[] strArray = ConvertToStringArray(myvalues);
                 foreach (string s in strArray)
                 {
                     Console.WriteLine(s);
                 }
                Console.WriteLine("i vokser!!");
                 }

            xlWorkBook.Close(true, misValue, misValue);
            xlApp.Quit();

            releaseObject(xlWorkSheet);
            releaseObject(xlWorkBook);
            releaseObject(xlApp);

            return "done";
        }

        public Schedule parseIntoSchedule(string filename)
        {
            int departments = 1;
            int days = 65;
            int types; //This value is found in the input file
            int slots = 24;
            int weeks = 13;

            int ExcelMaxRows = 65536;

            Schedule result = new Schedule(0,0,0,0);
            Excel.Application xlApp;
            Excel.Workbook xlWorkBook;
            Excel.Worksheet xlWorkSheet;
            object misValue = System.Reflection.Missing.Value;            

            xlApp = new Excel.Application();

            
            try
            {
                //Open up the excel workbook
                xlWorkBook = xlApp.Workbooks.Open(@filename, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "t", false, false, 0, true, 1, 0);
                weeks = xlWorkBook.Sheets.Count;
                days = weeks * 5;

                #region Find the number of types

                types = 0;
                int RowCount = 1;
                xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);

                while (xlWorkSheet.get_Range("B" + RowCount.ToString()).Value != null)
                {
                    //Count the number of diffenrent types. The input lists five days pr. skill so add a skill every fifth row.
                    if ((RowCount - 2) % 5 == 0)  //substract 1 because first row has column names
                    {
                        types++;
                    }
                    RowCount++;
                }
                #endregion


                result = new Schedule(departments, types, days, slots);

                for (int week = 0; week < weeks; week++)
                {

                    xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(week+1);
                    
                    int type = -1;

                    //Loop throughall rows in the sheet(week)
                    for (int row = 2; row < RowCount; row++)
                    {
                        //Count the number of diffenrent types. The input lists five days pr. skill so add a skill every fifth row.
                        if ((row - 2) % 5 == 0) type++;

                        Excel.Range range = xlWorkSheet.get_Range("A" + row.ToString(), "AD" + row.ToString());
                        System.Array myvalues = (System.Array)range.Cells.Value;
                        string[] strArray = ConvertToStringArray(myvalues);
                        if (!typer.Keys.Contains(type)) { typer.Add(type, strArray[1]); }
                        int slot = 0;
                        foreach (string s in strArray)
                        {
                            slot++;
                            if (slot >= 7)
                            {
                                double value = Math.Round(float.Parse(s), 0);
                                result.assign(0, type, ((row - 2) % 5)+(week*5), slot - 7, (int)value);
                            }
                        }
                    }
                    releaseObject(xlWorkSheet);
                }

                xlWorkBook.Close(true, misValue, misValue);
                xlApp.Quit();
                                
                releaseObject(xlWorkBook);
                releaseObject(xlApp);

            }
            catch (Exception e)
            {
                Console.Write(e.Message);
                Environment.Exit(-1);
            }

            return result;
        }

        string[] ConvertToStringArray(System.Array values)
        {

            // create a new string array
            string[] theArray = new string[values.Length];

            // loop through the 2-D System.Array and populate the 1-D String Array
            for (int i = 1; i <= values.Length; i++)
            {
                if (values.GetValue(1, i) == null)
                    theArray[i - 1] = "";
                else
                    theArray[i - 1] = (string)values.GetValue(1, i).ToString();
            }

            return theArray;
        }

        private void releaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                Console.WriteLine("Unable to release the Object " + ex.ToString());
            }
            finally
            {
                GC.Collect();
            }
        }

        public Schedule shiftsToSchedule(List<Shift> shifts,int departments,int types, int days, int slots)
        {
            Schedule result = new Schedule(departments, types, days, slots);
            foreach(Shift s in shifts)
            {
                for (int slot = s.StartSlot; slot < s.StartSlot + s.Slots; slot++)
                {
                    result.add(s.Department, s.Type, s.Day, slot, 1);
                }                
            }
            return result;
        }

        public void printToFile_cellByCell(string filename,Schedule input)
        {
            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();

            if (xlApp == null)
            {
                Console.WriteLine("EXCEL could not be started. Check that your office installation and project references are correct.");
                return;
            }

            Excel.Workbook wb = xlApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
            Excel.Worksheet ws = (Excel.Worksheet)wb.Worksheets[1];

            if (ws == null)
            {
                Console.WriteLine("Worksheet could not be created. Check that your office installation and project references are correct.");
            }

            // Select the Excel cells, in the range c1 to c7 in the worksheet.
            Excel.Range aRange = ws.get_Range("C1", "C7");

            if (aRange == null)
            {
                Console.WriteLine("Could not get a range. Check to be sure you have the correct versions of the office DLLs.");
            }

            // Fill the cells in the C1 to C7 range of the worksheet with the number 6.
            //Object[] args = new Object[1];
            //args[0] = 9;
            //aRange.GetType().InvokeMember("Value", BindingFlags.SetProperty, null, aRange, args);

            xlApp.Visible = false;
            //xlApp.DisplayAlerts = false;
            //xlApp.ScreenUpdating = false;
            //xlApp.UserControl = false;
            //xlApp.Interactive = false;

            Excel._Worksheet sheet = wb.ActiveSheet;

            //Print header
            try
                {
                Excel.Range header = (Excel.Range)sheet.Cells[1, 1];
                string nameString = "";
                nameString = String.Format("Afdeling");
                header.Value2 = nameString;
                header = (Excel.Range)sheet.Cells[1, 2];
                nameString = String.Format("Type");
                header.Value2 = nameString;
                header = (Excel.Range)sheet.Cells[1, 3];
                nameString = String.Format("Dag");
                header.Value2 = nameString;
                header = (Excel.Range)sheet.Cells[1, 4];
                nameString = String.Format("DayOfYear");
                header.Value2 = nameString;
                }
            catch (System.Runtime.InteropServices.COMException)
            {
            }

            for (int slot = 0; slot < input.Slots; slot++)
            {
                try
                {
                Excel.Range name = (Excel.Range)sheet.Cells[1, slot+5];
                string nameString = "";
                nameString = String.Format("{0}",slot);
                name.Value2 = nameString;
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                }
            }

            // print content
            int row = 1;
            for (int department = 0; department < input.Departments; department++)
                for (int type = 0; type < input.Types; type++)
                    for (int day = 0; day < input.Days; day++)
                    {
                        row++;
                        
                        Boolean wroteName = false;
                        while (!wroteName)
                        {
                            try
                            {
                                Excel.Range name = (Excel.Range)sheet.Cells[row, 1];
                                string nameString = "";
                                nameString = String.Format("Afdeling {0}", department);
                                name.Value2 = nameString;
                                wroteName = true;

                                name = (Excel.Range)sheet.Cells[row, 2];
                                nameString = String.Format("Type {0}", type);
                                name.Value2 = nameString;
                                wroteName = true;

                                name = (Excel.Range)sheet.Cells[row, 3];
                                string dayName ="";
                                switch (day % 5)
                                {
                                    case 0:
                                        dayName = "mandag";
                                        break;
                                    case 1:
                                        dayName = "tirsdag";
                                        break;
                                    case 2:
                                        dayName = "onsdag";
                                        break;
                                    case 3:
                                        dayName = "torsdag";
                                        break;
                                    case 4:
                                        dayName = "fredag";
                                        break;
                                }
                                nameString = String.Format("{0}", dayName);
                                name.Value2 = nameString;
                                wroteName = true;

                                name = (Excel.Range)sheet.Cells[row, 4];
                                nameString = String.Format("{0}", day);
                                name.Value2 = nameString;
                                wroteName = true;
                            }
                            catch (System.Runtime.InteropServices.COMException)
                            {
                            }
                        }

                        for (int slot = 0; slot < input.Slots; slot++)
                        {
                            Excel.Range depRange = (Excel.Range)sheet.Cells[row, slot + 5];                                                        
                            Boolean wroteResult = false;
                            while (!wroteResult)
                            {
                                try
                                {

                                    depRange.Value2 = input.getAssignment(department, type, day, slot);
                                    wroteResult = true;
                                }
                                catch (System.Runtime.InteropServices.COMException)
                                {
                                }
                            }

                        }
                    }
            xlApp.Visible = true;
            releaseObject(wb);
            releaseObject(xlApp);


        }

        public void printToFile(string filename, Schedule input)
        {
            Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
            
            if (xlApp == null)
            {
                Console.WriteLine("EXCEL could not be started. Check that your office installation and project references are correct.");
                return;
            }

            xlApp.Visible = true;
            Excel.Workbook wb = xlApp.Workbooks.Add();
            Worksheet xlSheet = null;
            Excel._Worksheet sheet = wb.ActiveSheet;
            Sheets xlSheets = wb.Sheets as Sheets;
            int dep=0;     
            while(xlSheets.Count<input.Departments){
            try
                {  
                    xlSheet = (Worksheet)xlSheets.Add();                                   
                    dep++;
                }
            catch (System.Runtime.InteropServices.COMException)
                {
                }
                
            }

            for (dep = 0; dep < input.Departments; dep++)
            {
                bool printed = false;
                xlSheet = xlSheets[dep + 1];
                int rows = input.Types * input.Days + 2;
                int columns = input.Slots + 3;
                var data = new object[rows, columns];
                data[0, 0] = ((Afdeling)dep).ToString();
                for (int slot = 0; slot < input.Slots; slot++)
                {
                    data[0, slot + 3] =string.Format("{0}:{1}", ((slot * 30 + 8 * 60) / 60),((slot * 30 + 8 * 60))%60);
                }
                int week = -1;

                for (int day = 0; day < input.Days; day++)
                {
                    if (day % 5 == 0) { week++; }
                    for (int type = 0; type < input.Types; type++)
                    {
                       int row = day * input.Types+type+1;
                            for (int slot = 0; slot < input.Slots; slot++)
                            {   
                                int col = slot + 3;
                                data[row, 0] = String.Format("{0}",typer[type]);
                                data[row, 1] = String.Format("Uge {0}",week+1);
                                data[row, 2] = Ugedage[day%5];
                                data[row, col] = input.getAssignment(dep, type, day, slot);
                            }
                    }
                }
                var startCell = (Range)xlSheet.Cells[1, 1];
                var endCell = (Range)xlSheet.Cells[rows, columns];
                var writeRange = xlSheet.Range[startCell, endCell];
                while (!printed)
                {
                    try
                    {
                        xlSheet.Name = ((Afdeling)dep).ToString();
                        writeRange.Value2 = data;
                        printed = true;
                    }
                    catch (System.Runtime.InteropServices.COMException)
                    {
                        printed = false;
                    }
                }
            }

            bool release = false;
            while (!release)
            {
                try
                {
                    xlApp.Visible = true;
                    releaseObject(wb);
                    releaseObject(xlApp);
                    release = true;

                }
                catch (System.Runtime.InteropServices.COMException)
                {
                }
            }


        }
    }

    
}
